﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024 LiLong                                                   **
**  This file is part of GnssLogs.                                              **
**                                                                              **
**  GnssLogs is free software: you can redistribute it and/or modify            **
**  it under the terms of the GNU Lesser General Public License as published by **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  GnssLogs is distributed in the hope that it will be useful,                 **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU Lesser General Public License for more details.                         **
**                                                                              **
**  You should have received a copy of the GNU Lesser General Public License    **
**  along with GnssLogs.  If not, see <https://www.gnu.org/licenses/>.          **
**********************************************************************************/
#pragma once

#include "../BESTPOS.h"
#include "LogHeaderDecoder.h"

namespace GnssLogs
{
namespace BESTPOSDecoder
{
using namespace tao::pegtl;
using Sync   = TAO_PEGTL_STRING("#BESTPOSA");
using Header = LogHeaderDecoder::SyncExpression<Sync>;
// clang-format off
struct SolStat : ascii::identifier {};
struct PosType : ascii::identifier {};
struct Lat : Floating {};
struct Lon : Floating {};
struct Hgt : Floating {};
struct Undulation : Floating {};
struct DatumIDRule : ascii::identifier {};
struct LatSigma : Floating {};
struct LonSigma : Floating {};
struct HgtSigma : Floating {};
struct StnID : StringLiteral {};
struct DiffAge : Floating {};
struct SolAge : Floating {};
struct SVS : star<digit> {};
struct SolnSVs : star<digit> {};
struct SolnL1SVs : star<digit> {};
struct SolnMultiSVs : star<digit> {};
struct Reserved : star<xdigit> {};
struct ExtSolStat : star<xdigit> {};
struct GalileoAndBeiDouSignalUsedMasksRule : star<xdigit> {};
struct GPSAndGLONASSSignalUsedMasksRule : star<xdigit> {};
// clang-format on

using Expression = seq<Header,
                       SolStat,
                       Split,
                       PosType,
                       Split,
                       Lat,
                       Split,
                       Lon,
                       Split,
                       Hgt,
                       Split,
                       Undulation,
                       Split,
                       DatumIDRule,
                       Split,
                       LatSigma,
                       Split,
                       LonSigma,
                       Split,
                       HgtSigma,
                       Split,
                       StnID,
                       Split,
                       DiffAge,
                       Split,
                       SolAge,
                       Split,
                       SVS,
                       Split,
                       SolnSVs,
                       Split,
                       SolnL1SVs,
                       Split,
                       SolnMultiSVs,
                       Split,
                       Reserved,
                       Split,
                       ExtSolStat,
                       Split,
                       GalileoAndBeiDouSignalUsedMasksRule,
                       Split,
                       GPSAndGLONASSSignalUsedMasksRule,
                       one<'*'>,
                       CRC32,
                       Tail>;

template<typename T>
struct Action
{
};

template<>
struct Action<Header> : LogHeaderDecoder::LogHeaderHelperNoSetValue
{
};

template<>
struct Action<SolStat> : EnumHelper<Action<SolStat>, SolutionStatus>
{
    static void setValue(BESTPOS::Data& data, SolutionStatus value) { data.solStat = value; }
};

template<>
struct Action<PosType> : EnumHelper<Action<PosType>, PositionOrVelocityType>
{
    static void setValue(BESTPOS::Data& data, PositionOrVelocityType value) { data.posType = value; }
};

template<>
struct Action<Lat> : DoubleHelper<Action<Lat>>
{
    static void setValue(BESTPOS::Data& data, double value) { data.lat = value; }
};

template<>
struct Action<Lon> : DoubleHelper<Action<Lon>>
{
    static void setValue(BESTPOS::Data& data, double value) { data.lon = value; }
};

template<>
struct Action<Hgt> : DoubleHelper<Action<Hgt>>
{
    static void setValue(BESTPOS::Data& data, double value) { data.hgt = value; }
};

template<>
struct Action<Undulation> : FloatHelper<Action<Undulation>>
{
    static void setValue(BESTPOS::Data& data, float value) { data.undulation = value; }
};

template<>
struct Action<DatumIDRule> : EnumHelper<Action<DatumIDRule>, DatumID>
{
    static void setValue(BESTPOS::Data& data, DatumID value) { data.datumId = value; }
};

template<>
struct Action<LatSigma> : FloatHelper<Action<LatSigma>>
{
    static void setValue(BESTPOS::Data& data, float value) { data.latSigma = value; }
};

template<>
struct Action<LonSigma> : FloatHelper<Action<LonSigma>>
{
    static void setValue(BESTPOS::Data& data, float value) { data.lonSigma = value; }
};

template<>
struct Action<HgtSigma> : FloatHelper<Action<HgtSigma>>
{
    static void setValue(BESTPOS::Data& data, float value) { data.hgtSigma = value; }
};

template<>
struct Action<StnID> : StringHelper<Action<StnID>>
{
    static void setValue(BESTPOS::Data& data, const std::string& value) { data.stnId = value; }
};

template<>
struct Action<DiffAge> : FloatHelper<Action<DiffAge>>
{
    static void setValue(BESTPOS::Data& data, float value) { data.diffAge = value; }
};

template<>
struct Action<SolAge> : FloatHelper<Action<SolAge>>
{
    static void setValue(BESTPOS::Data& data, float value) { data.solAge = value; }
};

template<>
struct Action<SVS> : IntHelper<Action<SVS>, uint8_t>
{
    static void setValue(BESTPOS::Data& data, uint8_t value) { data.svs = value; }
};

template<>
struct Action<SolnSVs> : IntHelper<Action<SolnSVs>, uint8_t>
{
    static void setValue(BESTPOS::Data& data, uint8_t value) { data.solnSVs = value; }
};

template<>
struct Action<SolnL1SVs> : IntHelper<Action<SolnL1SVs>, uint8_t>
{
    static void setValue(BESTPOS::Data& data, uint8_t value) { data.solnL1SVs = value; }
};

template<>
struct Action<SolnMultiSVs> : IntHelper<Action<SolnMultiSVs>, uint8_t>
{
    static void setValue(BESTPOS::Data& data, uint8_t value) { data.solnMultiSVs = value; }
};

template<>
struct Action<Reserved> : IntHelper<Action<Reserved>, uint8_t, 16>
{
    static void setValue(BESTPOS::Data& data, uint8_t value) { data.reserved = value; }
};

template<>
struct Action<ExtSolStat> : ExtendedSolutionStatusHelper<Action<ExtSolStat>>
{
    static void setValue(BESTPOS::Data& data, ExtendedSolutionStatus value) { data.extSolStat = value; }
};

template<>
struct Action<GalileoAndBeiDouSignalUsedMasksRule> : IntHelper<Action<GalileoAndBeiDouSignalUsedMasksRule>, uint8_t, 16>
{
    static void setValue(BESTPOS::Data& data, uint8_t value)
    {
        data.galileoAndBeiDouSignalUsedMasks = GalileoAndBeiDouSignalUsedMasks(value);
    }
};

template<>
struct Action<GPSAndGLONASSSignalUsedMasksRule> : IntHelper<Action<GPSAndGLONASSSignalUsedMasksRule>, uint8_t, 16>
{
    static void setValue(BESTPOS::Data& data, uint8_t value) { data.gpsAndGLONASSSignalUsedMasks = GPSAndGLONASSSignalUsedMasks(value); }
};

template<>
struct Action<CRC32> : CRC32Helper<Action<CRC32>>
{
    static void setValue(BESTPOS::Data& data, uint32_t value) { data.crc32 = value; }
};
} // namespace BESTPOSDecoder
} // namespace GnssLogs